﻿using System.Globalization;
using System.Windows;
using System.Windows.Media;

namespace FFmpegVideoClip.Lib.Controls
{
    internal class OutlineTextControl : FrameworkElement
    {
        private static void OnOutlineTextInvalidated(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((OutlineTextControl)d).CreateText(); }

        private Geometry? _textGeometry;
        private Geometry? _textHighLightGeometry;

        protected override void OnRender(DrawingContext drawingContext)
        {
            drawingContext.DrawGeometry(Fill, new Pen(Stroke, StrokeThickness), _textGeometry);
            if (Highlight == true)
            {
                drawingContext.DrawGeometry(null, new System.Windows.Media.Pen(Stroke, StrokeThickness), _textHighLightGeometry);
            }
        }

        public void CreateText()
        {
            FontStyle fontStyle = FontStyles.Normal;
            FontWeight fontWeight = FontWeights.Medium;

            if (Bold == true) fontWeight = FontWeights.Bold;
            if (Italic == true) fontStyle = FontStyles.Italic;

            FormattedText formattedText = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, 
                new Typeface(Font, fontStyle, fontWeight, FontStretches.Normal), FontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip);

            _textGeometry = formattedText.BuildGeometry(new Point(0, 0));

            if (Highlight == true)
            {
                _textHighLightGeometry = formattedText.BuildHighlightGeometry(new Point(0, 0));
            }
        }

        public bool Bold { get => (bool)GetValue(BoldProperty); set => SetValue(BoldProperty, value); }
        public static readonly DependencyProperty BoldProperty = DependencyProperty.Register("Bold", typeof(bool), typeof(OutlineTextControl),
            new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));


        public Brush Fill { get => (Brush)GetValue(FillProperty); set => SetValue(FillProperty, value); }
        public static readonly DependencyProperty FillProperty = DependencyProperty.Register("Fill", typeof(System.Windows.Media.Brush), typeof(OutlineTextControl),
            new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Black), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public FontFamily Font { get => (FontFamily)GetValue(FontProperty); set => SetValue(FontProperty, value); }
        public static readonly DependencyProperty FontProperty = DependencyProperty.Register("Font", typeof(FontFamily), typeof(OutlineTextControl), new FrameworkPropertyMetadata(new FontFamily("Arial"), 
            FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public double FontSize { get => (double)GetValue(FontSizeProperty); set => SetValue(FontSizeProperty, value); }
        public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(OutlineTextControl), 
            new FrameworkPropertyMetadata((double)48.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public bool Highlight { get => (bool)GetValue(HighlightProperty); set => SetValue(HighlightProperty, value); }
        public static readonly DependencyProperty HighlightProperty = DependencyProperty.Register("Highlight", typeof(bool), typeof(OutlineTextControl), 
            new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public bool Italic { get => (bool)GetValue(ItalicProperty); set => SetValue(ItalicProperty, value); }
        public static readonly DependencyProperty ItalicProperty = DependencyProperty.Register("Italic", typeof(bool), typeof(OutlineTextControl), 
            new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public Brush Stroke { get => (Brush)GetValue(StrokeProperty); set => SetValue(StrokeProperty, value); }
        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register("Stroke", typeof(Brush), typeof(OutlineTextControl), 
            new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Teal), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public ushort StrokeThickness { get => (ushort)GetValue(StrokeThicknessProperty); set => SetValue(StrokeThicknessProperty, value); }
        public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(ushort), typeof(OutlineTextControl),
            new FrameworkPropertyMetadata((ushort)0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(OutlineTextControl),
            new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null));

        public bool IsShowStateAnim { get => (bool)GetValue(IsShowStateAnimProperty); set => SetValue(IsShowStateAnimProperty, value); }
        public static readonly DependencyProperty IsShowStateAnimProperty = DependencyProperty.Register(nameof(IsShowStateAnim), typeof(bool), typeof(OutlineTextControl), new PropertyMetadata(false));

    }
}
